package com.itheima;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @auther Macrydy
 * @date 2020/7/12 11:04
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //打开通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress(10001));
        //把服务端通道设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //设置选择器
        //Selector --- 选择器
        Selector selector = Selector.open();
        //5.绑定选择器和服务端通道
        serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);

        //循环查看选择器中有没有客户连接进来
        while(true){
            //选择器会监视客户端通道的状态.
            //6.返回值就表示此时有多少个客户端来连接.
            int count = selector.select();
            if(count != 0){
                System.out.println("有客户端来连接了");
                //7.会遍历所有的服务端通道.看谁准备好了,谁准备好了,就让谁去连接.
                //获取所有服务端通道的令牌,并将它们都放到一个集合中,将集合返回.
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while(iterator.hasNext()){
                    //selectionKey 依次表示每一个服务端通道的令牌
                    SelectionKey selectionKey = iterator.next();
                    if(selectionKey.isAcceptable()){
                        //可以通过令牌来获取到了一个已经就绪的服务端通道
                        ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                        //客户端的延伸通道
                        SocketChannel socketChannel = ssc.accept();
                        //将客户端延伸通道设置为非阻塞的
                        socketChannel.configureBlocking(false);
                        //将创建的延伸通道绑定选择器
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    //选择器是可以监视所有与之绑定过的通道的，所以第一次连接因为还没创建延伸通道，所以不会进入此，如果
                    //selectionKey.isReadable()为true则说明当前通道已经有数据可读且当前必然为延伸通道
                    }else if(selectionKey.isReadable()){
                        //当前通道已经做好了读取的准备(延伸通道)
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        ByteBuffer byteBuffer1 = ByteBuffer.allocate(5);
                        //socketChannel.read(byteBuffer1);
                        int len;
                        while((len = socketChannel.read(byteBuffer1)) > 0){
                            System.out.println(len);
                            byteBuffer1.flip();
                            System.out.println(new String(byteBuffer1.array(),0,len));
                            byteBuffer1.clear();
                        }
                        //给客户端的回写数据
                        socketChannel.write(ByteBuffer.wrap("哎哟喂好疼啊!!!".getBytes()));
                        socketChannel.close();
                    }
                    iterator.remove();
                }
            }
        }
    }
}
